package il.ac.braude.sona.control;

import il.ac.braude.sona.constants.Mssg;
import il.ac.braude.sona.constants.P;
import il.ac.braude.sona.constants.Resources;
import il.ac.braude.sona.constants.TestingParamKit;
import il.ac.braude.sona.entities.PeriodicReport;
import il.ac.braude.sona.gui.forms.FormFrame;
import il.ac.braude.sona.gui.forms.FormListener;
import il.ac.braude.sona.gui.forms.myforms.ReportSelectForm;
import il.ac.braude.sona.gui.infogui.DelaysGraphFrame;
import il.ac.braude.sona.gui.infogui.ExtensionGraphFrame;
import il.ac.braude.sona.gui.infogui.InfoPanel;
import il.ac.braude.sona.gui.infogui.PeriodicReportFrame;
import il.ac.braude.sona.gui.infogui.ReportInfoFrame;
import il.ac.braude.sona.gui.list_table.ListTable;
import il.ac.braude.sona.gui.list_table.ListTableModel;
import il.ac.braude.sona.gui.mytables.ReportsTableFrame;
import il.ac.braude.sona.ocsf.client.Client;
import il.ac.braude.sona.ocsf.client.ServerResponseListener;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import javax.swing.JOptionPane;
/**
 * The ReportsController contains all methods to handle reports views
 *  
 * @author Ofek Ron
 * @author Avihay Avitan
 * @author Nitzan Inbar
 * @author Sasha Rosenthal
 */
public class ReportsController implements FormListener, ActionListener  {
	/**
	 * HashMap contains data for reports from DB
	 */
	private HashMap<String, String> reportAnswer;
	private boolean prev_flag = false;
	/**
	 * ArrayList of reports data
	 */
	private ArrayList<PeriodicReport> reports;
	

	private HashMap<String, HashMap<String,String>> reportAnswerPeriodic;

	/**
	 * The form to select report to view
	 */

	private ReportSelectForm selectReportform;
	/**
	 * The report fram.
	 */
	private ReportInfoFrame rinfo ;

	private TestingParamKit myKit=TestingParamKit.getTestingKit();
	public PeriodicReportFrame frame ;
	/**
	 * selectReport opens ReportSelectForm to choose one of the offered reports
	 */
	public void selectReport() {
		selectReportform = new ReportSelectForm("select Report",this);
		selectReportform.addFormListener(ReportsController.this);
		selectReportform.setResizable(true);
		if (!myKit.TestMode)
		selectReportform.showFrame();
	}
	@Override
	
	public void onFormCanceled(FormFrame formFrame) {
		// TODO Auto-generated method stub

	}
	@Override
	public void onFormSubmited(FormFrame formFrame, ArrayList<Object> values) {
		values.remove("");
		values.remove("");
		String s1 = new String((String) values.get(0));
		execReportInfo(s1,values);
	}

	/**
	 * execReportInfo send message to server for report data and 
	 * initiate new ReportInfoFrame to view report data and grahps
	 * 
	 * @param reportName - The name of required report
	 * @param values - the form values contains the information required
	 */
	public void execReportInfo(final String reportName, final ArrayList<Object> values) {
		try {
			Mssg mssg = new Mssg(reportName.toLowerCase(),values);
			selectReportform.showMessege(Resources.Strings.Connecting);
			Client.getInstance().sendToServer(new ServerResponseListener() {

				@SuppressWarnings("unchecked")
				@Override
				public void onServerResponse(Mssg mssg) {
					if (mssg.is(P.error)) {
						selectReportform.showMessege("bad work");
						return;
					}
					if (reportName.equals(Resources.Strings.P_report)) reportAnswerPeriodic =  (HashMap<String,HashMap<String,String>>) mssg.getMessege();
					else if (reportName.equals(Resources.Strings.E_report)) reportAnswer =  (HashMap<String,String>) mssg.getMessege();
					else if (reportName.equals(Resources.Strings.D_report)) reportAnswer =  (HashMap<String,String>) mssg.getMessege();
					if ((reportAnswer != null)||(reportAnswerPeriodic != null))   {
						rinfo = new ReportInfoFrame(reportName);
						InfoPanel p = new InfoPanel();
						if (!prev_flag)
						p.addTitleWithUnderline(reportName+": "+ rinfo.dateFormat.format(rinfo.date));
						else
						{
							p.addTitleWithUnderline(reportName+": dates: "+values.get(1)+" - "+values.get(2));
							prev_flag = false;
						}
						if (reportName.equals(Resources.Strings.P_report)) 
							execPgraph(reportName,reportAnswerPeriodic,p);
						else if (reportName.equals(Resources.Strings.D_report))
							execDgraph(reportName,reportAnswer,p);
						
						else {
							Set<Entry<String, String>> reportData = reportAnswer.entrySet();
							Iterator<Entry<String, String>> mapitarator = reportData.iterator();
							while (mapitarator.hasNext())
							{
								Entry<String, String> map = mapitarator.next();
								p.addInfoRow(map.getKey(),map.getValue());
							}
							execEgraph(reportName,reportAnswer,p);
						}


					} else
						JOptionPane.showMessageDialog(selectReportform,
								String.format("Report Error"));
					selectReportform.dispose();
					selectReportform = null;

				}
			}, mssg);

		} catch (Exception e) {
			e.printStackTrace();
			selectReportform.dispose();
			selectReportform = null;
		}


	}
	
	/**
	 * execEgraph initiate the extention report fram
	 * 
	 * @param reportName - The name of required report
	 * @param reportAnswer - HashMap contains data for reports from DB
	 * @param p - the info panel contains the text data
	 */
	protected void execEgraph(String reportName,HashMap<String, String> reportAnswer, InfoPanel p) {
		ExtensionGraphFrame frame1 = new ExtensionGraphFrame(reportName,reportAnswer);
		frame1.add(p,BorderLayout.WEST);
		frame1.setExtendedState(frame1.getExtendedState() | Frame.MAXIMIZED_BOTH);
		frame1.showFrame();
	}
	
	/**
	 * execPgraph initiate the periodic report fram
	 * 
	 * @param reportName - The name of required report
	 * @param reportAnswerPeriodic2 - HashMap contains data for reports from DB
	 * @param p - the info panel contains the text data
	 */
	protected void execPgraph(String reportName,HashMap<String, HashMap<String, String>> reportAnswer2,InfoPanel p) {
		frame = new PeriodicReportFrame(reportAnswer2,reportName);
	
		p.addInfoRow("Total working days",reportAnswer2.get("Total").get("Total days spent"));
		System.out.println("Check: " +reportAnswer2);
		if (myKit.TestMode)
			myKit.notifyTester();
		else{
		frame.add(p,BorderLayout.NORTH);
		frame.setExtendedState(frame.getExtendedState() | Frame.MAXIMIZED_BOTH);
		frame.showFrame();
		}
	}
	
	/**
	 * execPgraph initiate the delays report fram
	 * 
	 * @param reportName - The name of required report
	 * @param reportAnswer - HashMap contains data for reports from DB 
	 * @param p - the info panel contains the text data
	 */
	protected void execDgraph(String reportName,HashMap<String, String> reportAnswer,InfoPanel p) { 
		System.out.println("im here");
		p.addInfoRow("Total request delayed", reportAnswer.get("Total request delayed"));
		p.addInfoRow("Total standard deviation.", reportAnswer.get("Total standard deviation."));
		p.addInfoRow("Total days delayed", reportAnswer.get("Total days delayed"));
		p.addInfoRow("Median for all", reportAnswer.get("Median for all"));
		DelaysGraphFrame frame1 = new DelaysGraphFrame(reportAnswer,reportName);
		frame1.add(p,BorderLayout.WEST);
		frame1.setExtendedState(frame1.getExtendedState() | Frame.MAXIMIZED_BOTH);
		frame1.showFrame();

	}
	@Override
	public void actionPerformed(ActionEvent arg0) {
		try {
			final ReportsTableFrame tableFrame = new ReportsTableFrame(this);
			Mssg mssg = new Mssg(P.getReports);
			selectReportform.showMessege(Resources.Strings.Connecting);
			Client.getInstance().sendToServer(new ServerResponseListener() {

				@SuppressWarnings("unchecked")
				@Override
				public void onServerResponse(Mssg mssg) {
					if (mssg.is(P.error)) {
						selectReportform.showMessege("bad work");
						return;
					}
					if ((reports = (ArrayList<PeriodicReport>)mssg.getMessege())!= null)
					   {
						tableFrame.getContentPane().removeAll();
						ListTableModel<PeriodicReport> model = new ListTableModel<PeriodicReport>(reports);
						tableFrame.setTable(new ListTable<PeriodicReport>(model));
						tableFrame.setResizable(false);
						selectReportform.dispose();
						tableFrame.showFrame();
					
					   }
					else {
						selectReportform.dispose();
						selectReportform = null;
					}
			
				}
			}, mssg);

		} catch (Exception e) {
			e.printStackTrace();
			selectReportform.dispose();
			selectReportform = null;
		}
		
	}
	/**
	 * Create info fram for saved periodic report
	 * @param report -  the PeriodicReport entity
	 * @param reportName - the report name
	 */
	public void periodicReport(PeriodicReport report,String reportName) {
		prev_flag = true;
		ArrayList<Object> values = new ArrayList<Object>();
		values.add(reportName);
		values.add(report.getFrom());
		values.add(report.getTo());
		this.execReportInfo(reportName, values);
		
	}
	
	}


